home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 8: LINUX Games
/
Linux Cubed Series 8 - LINUX Games.iso
/
games
/
x11
/
rpg
/
crossfir.92
/
crossfir
/
crossfire-0.92.5
/
common
/
readable.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-07-24
|
27KB
|
859 lines
/* This file contains code relevant to the BOOKS hack -- designed
* to allow randomly occuring messages in non-magical texts.
*/
/* laid down initial file - dec 1995. -b.t. thomas@astro.psu.edu */
#include <global.h>
#include <read.h>
#include <book.h>
#include <living.h>
#include <spells.h>
/* This flag is useful to see what kind of output messages are created */
/* #define BOOK_MSG_DEBUG */
/* init_readable() - initialize linked lists utilized by
* message functions in tailor_readable_ob() */
void init_readable( void ) {
static int did_this;
if(!did_this) did_this=1;
else return;
fprintf(logfile,"\nInitializing reading data...");
init_msgfile();
init_mon_info();
}
/* tailor_readable_ob()- The main routine. This chooses a random
* message to put in given readable object (type==BOOK) which will
* be referred hereafter as a 'book'. We use the book level to de-
* termine the value of the information we will insert. Higher
* values mean the book will (generally) have better/more info.
* See individual cases as to how this will be utilized.
* "Book" name/content length are based on the weight of the
* document. If the value of msg_type is negative, we will randomly
* choose the kind of message to generate.
* -b.t. thomas@astro.psu.edu
*/
void tailor_readable_ob (object *book, int msg_type) {
char msgbuf[BOOK_BUF];
int level=book->level?(RANDOM()%book->level)+1:1;
int book_buf_size;
/* safety */
if(book->type!=BOOK) return;
/* lets give the "book" a new name, which may be a compound word */
change_book_name(book);
if(level<=0) return; /* if no level no point in doing any more... */
book_buf_size = BOOKSIZE(book);
/* ...but lets not exceed the actual max buffer!... */
if(book_buf_size>BOOK_BUF) book_buf_size = BOOK_BUF;
/* &&& The message switch &&& */
/* Below all of the possible types of messages in the "book"s.
* if you add another case, make sure all are reachable by the
* random number generator */
switch(msg_type>0?msg_type:(RANDOM()%6+1)) {
case 1: /* monster attrib */
strcpy(msgbuf, mon_info_msg(level,book_buf_size));
break;
case 2: /* artifact attrib */
strcpy(msgbuf, artifact_msg(level,book_buf_size));
break;
case 3: /* grouping spells/prayers by path */
strcpy(msgbuf, spellpath_msg(level,book_buf_size));
break;
case 4: /* describe an alchemy formula */
#ifdef ALCHEMY
strcpy(msgbuf, formula_msg(level,book_buf_size));
#else
strcpy(msgbuf, msgfile_msg(level,book_buf_size));
#endif
break;
case 5: /* bits of information about a god */
#ifdef MULTIPLE_GODS
strcpy(msgbuf, god_info_msg(level,book_buf_size));
#else
strcpy(msgbuf, msgfile_msg(level,book_buf_size));
#endif
break;
case 6: /* use info list in lib/ */
default:
strcpy(msgbuf, msgfile_msg(level,book_buf_size));
break;
}
strcat(msgbuf,"\n"); /* safety -- we get ugly map saves/crashes w/o this */
if(strlen(msgbuf)>1) {
if(book->msg) free_string(book->msg);
book->msg=add_string(msgbuf);
}
}
/* change_book_name() - give a new, fancier name to generated
* objects of type BOOK and SPELLBOOK.
*/
void change_book_name (object *book) {
int nbr = sizeof(book_descrpt)/sizeof(char *);
char name[MAX_BUF];
/* build up a new name buffer in 2 steps */
/* first the name of the book. */
switch(book->type) {
case BOOK: /* Name based on weight */
if(book->weight>2000) {
nbr = sizeof(heavy_book_name)/sizeof(char *);
strcpy(name,heavy_book_name[RANDOM()%nbr]);
} else if(book->weight<2001) {
nbr = sizeof(light_book_name)/sizeof(char *);
strcpy(name,light_book_name[RANDOM()%nbr]);
}
/* lets give the book an author */
if(!book->title&&(strlen(name)<20)&&!(RANDOM()%2))
add_author(book);
break;
case SPELLBOOK: /* depends on mage/clerical */
if(!strcmp(book->arch->name,"cleric_book")) {
nbr = sizeof(priest_book_name)/sizeof(char *);
strcpy(name,priest_book_name[RANDOM()%nbr]);
} else {
nbr = sizeof(mage_book_name)/sizeof(char *);
strcpy(name,mage_book_name[RANDOM()%nbr]);
}
break;
default:
LOG(llevError,"change_book_name() called w/ illegal obj type.\n");
return;
}
/* second, sometimes we give a book description */
if(!RANDOM()%3) sprintf(name,"%s %s",book_descrpt[RANDOM()%nbr],name);
if(book->name) free_string(book->name);
book->name = add_string(name);
}
/* add_book_author() */
void add_author (object *op) {
char name[MAX_BUF];
int nbr = sizeof(book_author)/sizeof(char *);
sprintf(name,"of %s",book_author[RANDOM()%nbr]);
op->title=add_string(name);
}
/* msgfile_msg() - generate a message drawn randomly from a
* file in lib/. Level currently has no effect on the message
* which is returned.
*/
char * msgfile_msg (int level, int booksize) {
static char retbuf[BOOK_BUF];
int i,msgnum;
linked_char *msg=NULL;
/* get a random message for the 'book' from linked list */
if(nrofmsg>1) {
msg = first_msg;
msgnum=RANDOM()%nrofmsg;
for(i=0;msg&&i<nrofmsg&&i!=msgnum;i++)
msg=msg->next;
}
if(msg&&!book_overflow(retbuf,msg->name,booksize))
strcpy(retbuf,msg->name);
else
sprintf(retbuf,"\n <undecipherable text>");
#ifdef BOOK_MSG_DEBUG
LOG(llevDebug,"\n info_list_msg() created strng: %d\n",strlen(retbuf));
fprintf(logfile," MADE THIS:\n%s\n",retbuf);
#endif
return retbuf;
}
/* init_msgfile() - if not called before, initialize the info list */
void init_msgfile ( void ) {
FILE *fp;
char buf[MAX_BUF], msgbuf[HUGE_BUF], fname[MAX_BUF], *cp;
int comp;
static int did_init_msgfile;
if(did_init_msgfile) return;
did_init_msgfile=1;
sprintf(fname, "%s/messages", LibDir);
if ((fp = open_and_uncompress(fname, 0, &comp)) != NULL) {
linked_char *tmp=NULL;
while (fgets(buf, MAX_BUF, fp)!=NULL) {
if (*buf=='#') continue;
if((cp=strchr(buf,'\n'))!=NULL) *cp='\0';
cp=buf;
while(*cp==' ') /* Skip blanks */
cp++;
if(!strncmp(cp, "ENDMSG", 6)) {
if(strlen(msgbuf)>BOOK_BUF) {
LOG(llevDebug,"Warning: this string exceeded max book buf size:");
LOG(llevDebug," %s",msgbuf);
}
tmp->name = add_string(msgbuf);
tmp->next = first_msg;
first_msg = tmp;
nrofmsg++; continue;
}
else if(!strncmp(cp, "MSG", 3)) {
tmp = (linked_char*) malloc(sizeof(linked_char));
strcpy(msgbuf," "); /* reset msgbuf for new message */
continue;
} else if(!buf_overflow(msgbuf,cp,HUGE_BUF-1)) {
strcat(msgbuf,cp); strcat(msgbuf,"\n");
}
}
close_and_delete(fp, comp);
}
#ifdef BOOK_MSG_DEBUG
LOG(llevDebug,"\ninit_info_listfile() got %d messages.\n",nrofmsg);
#endif
}
#ifdef ALCHEMY
/* formula_msg() - generate a message detailing the properties
* of a randomly selected alchemical formula.
*/
char * formula_msg (int level, int booksize) {
static char retbuf[BOOK_BUF];
recipelist *fl;
recipe *formula=NULL;
int chance;
/* the higher the book level, the more complex (ie number of
* ingredients) the formula can be.
*/
fl = get_formulalist(((RANDOM()%level)/3)+1);
if(!fl) fl=get_formulalist(1); /* safety */
if(fl->total_chance==0) {
strcpy(retbuf,"\n <undecipherable message> \n");
return retbuf;
}
/* get a random formula, weighted by its bookchance */
chance = RANDOM()%fl->total_chance;
for(formula=fl->items;formula!=NULL;formula=formula->next) {
chance -= formula->chance;
if(chance<=0) break;
}
/* preamble */
strcpy(retbuf,"Herein is described an alchemical proceedure: \n");
/* looks like a formula was found. Base the amount
* of information on the booklevel and the spellevel
* of the formula. */
if(formula) {
char *op_name=NULL;
archetype *at;
int nindex=nstrtok(formula->arch_name,",");
/* construct name of object to be made*/
if(nindex>1) {
int rnum = RANDOM()%nindex;
op_name = strtok(formula->arch_name,",");
while(rnum) { op_name = strtok(NULL,","); rnum--; }
} else
op_name = formula->arch_name;
if((at=find_archetype(op_name))!=(archetype *)NULL)
op_name = at->clone.name;
else
LOG(llevError,"formula_msg() can't find arch %s for formula.",
op_name);
/* item name */
if(strcmp(formula->title,"NONE"))
sprintf(retbuf,"%sThe %s of %s",retbuf,op_name,formula->title);
else {
sprintf(retbuf,"%sThe %s",retbuf,op_name);
if(at->clone.title) {
strcat(retbuf," ");
strcat(retbuf,at->clone.title);
}
}
/* ingredients to make it */
if (formula->ingred !=NULL) {
linked_char *next;
strcat(retbuf," may be made using the \nfollowing ingredients:\n");
for (next=formula->ingred; next!=NULL; next=next->next) {
strcat(retbuf,next->name); strcat(retbuf,"\n");
}
} else
LOG(llevError,"formula_msg() no ingredient list for object %s of %s",
op_name,formula->title);
} else
strcat(retbuf," <indescipherable text>\n");
#ifdef BOOK_MSG_DEBUG
LOG(llevDebug,"\n formula_msg() created strng: %d\n",strlen(retbuf));
fprintf(logfile," MADE THIS:\n%s\n",retbuf);
#endif
return retbuf;
}
#endif
/* mon_info_msg() - generate a message detailing the properties
* of a randomly selected monster.
*/
char * mon_info_msg (int level, int booksize) {
static char retbuf[BOOK_BUF];
char tmpbuf[HUGE_BUF];
object *tmp;
/*preamble */
strcpy(retbuf,"This beastuary contains:");
/* lets print info on as many monsters as will fit in our
* document.
*/
while((tmp=get_random_mon(level*3))!=NULL) {
/* monster description */
sprintf(tmpbuf,"\n---\n%s",mon_desc(tmp));
if(!book_overflow(retbuf,tmpbuf,booksize))
strcat(retbuf,tmpbuf);
else break;
}
#ifdef BOOK_MSG_DEBUG
LOG(llevDebug,"\n mon_info_msg() created strng: %d\n",strlen(retbuf));
fprintf(logfile," MADE THIS:\n%s\n",retbuf);
#endif
return retbuf;
}
char * mon_desc ( object *mon ) {
static char retbuf[HUGE_BUF];
sprintf(retbuf," *** %s ***\n",mon->name);
strcat(retbuf,describe_item(mon));
return retbuf;
}
/* get_random_mon() - returns a random monster slected from linked
* list of all monsters in the current game. If level is non-zero,
* then only monsters greater than that level will be returned.
*/
object *get_random_mon ( int level ) {
objectlink *mon=first_mon_info;
int i=0,monnr;
/* safety check. Problem w/ init_mon_info list? */
if(!nrofmon||!mon) return (object *) NULL;
/* lets get a random monster from the mon_info linked list */
monnr = RANDOM()%nrofmon;
do {
mon = mon->next;
i++;
} while (i<monnr);
/* now, we only print info on monsters w/ appropriate level */
if(level>0) {
int passed_once = 0;
while (mon->ob->level>level)
if(mon->next)
mon = mon->next;
else if(!passed_once) {
mon = first_mon_info;
passed_once = 1;
} else {
LOG(llevError,"get_random_mon() couldnt return monster for level %d\n",
level);
return (object *) NULL;
}
}
return mon->ob;
}
/* init_mon_info() - creates the linked list of pointers to
* monster archetype objects if not called previously
*/
void init_mon_info ( void ) {
archetype *at;
static int did_init_mon_info;
if(!did_init_mon_info) did_init_mon_info=1;
else return;
for(at=first_archetype;at!=NULL;at=at->next) {
if (QUERY_FLAG(&at->clone,FLAG_MONSTER)&&
(!QUERY_FLAG(&at->clone,FLAG_CHANGING)
||QUERY_FLAG(&at->clone,FLAG_UNAGGRESSIVE))
) {
objectlink *mon = (objectlink *) malloc(sizeof(objectlink));
mon->ob = &at->clone;
mon->id = nrofmon;
if(first_mon_info)
mon->next = first_mon_info;
first_mon_info = mon;
nrofmon++;
}
}
LOG(llevDebug,"init_mon_info() got %d monsters\n",nrofmon);
}
/* spellpath_msg() - generate a message detailing the member
* spells/prayers (and some of their properties) belonging to
* a given spellpath.
*/
char * spellpath_msg (int level, int booksize) {
static char retbuf[BOOK_BUF];
char tmpbuf[BOOK_BUF];
int path=(RANDOM()%(NRSPELLPATHS+1)-1),prayers=RANDOM()%2;
int i=0,did_first_sp=0;
uint32 pnum = (path==-1) ? PATH_NULL : spellpathdef[path];
/* Preamble */
sprintf(retbuf,"Herein are detailed the names of %s\n",
!(prayers) ? "spells" : "prayers");
if(path==-1)
strcat(retbuf,"having no known spell path.\n");
else
sprintf(retbuf,"%sbelonging to the path of %s:\n",retbuf,
spellpathnames[path]);
/* Now go through the entire list of spells. Add appropriate spells
* in our message buffer */
do {
if((spells[i].books||prayers)&&spells[i].cleric==prayers
&&(pnum&spells[i].path)) {
/* book level determines max spell level to show
* thus higher level books are more comprehensive */
if(spells[i].level>(level*3)) {
i++;
continue;
}
strcpy(tmpbuf,spells[i].name);
if(book_overflow(retbuf,tmpbuf,booksize))
break;
else {
if(did_first_sp) strcat(retbuf,",\n");
did_first_sp=1;
strcat(retbuf,tmpbuf);
}
}
i++;
} while(i<NROFREALSPELLS);
/* Geez, no spells were generated. */
if(!did_first_sp)
if(RANDOM()%4) /* usually, lets make a recursive call... */
sprintf(retbuf, spellpath_msg(level,booksize));
else /* give up, cause knowning no spells exist for path is info too. */
strcat(retbuf,"\n - no known spells exist -\n");
else {
#ifdef BOOK_MSG_DEBUG
LOG(llevDebug,"\n spellpath_msg() created strng: %d\n",strlen(retbuf));
fprintf(logfile," MADE THIS: path=%d pray=%d\n%s\n",path,prayers,retbuf);
#endif
strcat(retbuf,"\n");
}
return retbuf;
}
/* artifact_msg() - generate a message detailing the properties
* of 1-6 artifacts drawn sequentially from the artifact list.
*/
char *artifact_msg (int level, int booksize) {
artifactlist *al=NULL;
artifact *art;
int chance,i,type,index;
int book_entries=level>5?RANDOM()%3+RANDOM()%3+2:RANDOM()%level+1;
char *ch, name[MAX_BUF],buf[BOOK_BUF],sbuf[MAX_BUF];
static char retbuf[BOOK_BUF];
object *tmp=NULL;
/* values greater than 5 create msg buffers that are too big! */
if(book_entries>5) book_entries=5;
/* lets determine what kind of artifact type randomly.
* Right now legal artifacts only come from those listed
* in art_name_array. Also, we check to be sure an artifactlist
* for that type exists!
*/
do {
index = RANDOM()%(sizeof(art_name_array)/sizeof(arttypename));
type=art_name_array[index].type;
al = find_artifactlist(type);
} while(al==NULL);
/* There is no reason to start on the artifact list at the begining. Lets
* take our starting position randomly... */
art=al->items;
for(i=RANDOM()%level+RANDOM()%2+1;i>0;i--) {
if(art==NULL) art=al->items; /* hmm, out of stuff, loop back around */
art=art->next;
}
/* the base 'generic' name for our artifact */
sprintf(name,art_name_array[index].name);
/* Ok, lets print out the contents */
sprintf(retbuf,"Herein %s detailed %s...\n",book_entries>1?"are":"is",
book_entries>1?"some artifacts":"an artifact");
/* artifact msg attributes loop. Lets keep adding entries to the 'book'
* as long as we have space up to the allowed max # (book_entires)
*/
while(book_entries>0){
if(art==NULL) art=al->items;
/* separator of items */
strcpy(buf,"--- \n");
/* Name */
if (art->allowed!=NULL&&strcmp(art->allowed->name,"All")) {
linked_char *temp,*next=art->allowed;
do {
temp=next;
next=next->next;
} while ((next!=(linked_char *) NULL)&&!RANDOM()%2);
sprintf(buf,"%s A %s of %s",buf,temp->name,art->item->name);
}
else /* default name is used */
sprintf(buf,"%s The %s of %s",buf,name,art->item->name);
/* chance of finding */
chance = 100 * ((float) art->chance/al->total_chance);
if(chance>=20) sprintf(sbuf,"an uncommon");
else if(chance>=10) sprintf(sbuf,"an unusual");
else if(chance>=5) sprintf(sbuf,"a rare");
else sprintf(sbuf,"a very rare");
sprintf(buf,"%s is %s\n",buf,sbuf);
/* value of artifact */
sprintf(buf,"%s item with a value that is %d times normal.\n",
buf,art->item->value);
/* include the message about the artifact, if exists, and book
* level is kinda high */
if(art->item->msg&&(RANDOM()%4+1)<level&&
!((strlen(art->item->msg)+strlen(buf))>BOOK_BUF))
sprintf(buf,"%s %s",buf,art->item->msg);
/* properties of the artifact */
tmp=get_object();
add_abilities(tmp,art->item);
tmp->type = type;
SET_FLAG(tmp,FLAG_IDENTIFIED);
if((ch=describe_item(tmp))!=NULL&&strlen(ch)>1)
sprintf(buf,"%s Properties of this artifact include: \n %s \n",
buf,ch);
/* add the buf if it will fit */
if(!book_overflow(retbuf,buf,booksize))
strcat(retbuf,buf);
else break;
art=art->next;
book_entries--;
}
#ifdef BOOK_MSG_DEBUG
LOG(llevDebug,"artifact_msg() created strng: %d\n",strlen(retbuf));
fprintf(logfile," MADE THIS:\n%s",retbuf);
#endif
return retbuf;
}
/* arttype_has_name() returns the array value if the artifact is
* listed in art_name_array */
int arttype_has_name (int value) {
int i,number=sizeof(art_name_array)/sizeof(arttypename);
for(i=0;i<number;i++)
if(art_name_array[i].type==value) return i;
return -1;
}
/* god_info_msg() - generate a message detailing the properties
* of a random god. Used by the book hack. b.t.
*/
char *god_info_msg (int level, int booksize) {
static char retbuf[BOOK_BUF];
char *name=NULL, buf[BOOK_BUF];
int i,introlen;
int godnr=RANDOM()%NROFGODS; /* get a random god to 'profile' */
name=Gods[godnr].name;
if(name==NULL) return (char *) NULL; /* oops, problems...*/
/* preamble..*/
sprintf(retbuf,"This document contains knowledge concerning\n");
sprintf(retbuf,"%sthe diety %s",retbuf,name);
/* Always have as default information the god's descriptive terms. */
if(nstrtok(Gods[godnr].desc,",")>0) {
strcat(retbuf,", known as");
strcat(retbuf,strtoktolin(Gods[godnr].desc,","));
} else
strcat(retbuf,"...");
strcat(retbuf,"\n ---\n");
introlen = strlen(retbuf); /* so we will know if no new info is added later */
/* Information about the god is random, and based on the level of the
* 'book'. Probably there is a more intellegent way to implement
* this ...
*/
while(level>0) {
sprintf(buf," ");
if(level==2&&RANDOM()%2) { /* enemy god */
char *enemy=Gods[godnr].enemy;
if(enemy) sprintf(buf,"The gods %s and %s are enemies.\n ---\n",
name,enemy);
}
if(level==3&&RANDOM()%2) { /* enemy race, what the god's holy word effects */
char *enemy=Gods[godnr].enemy_race;
if(enemy&&!(Gods[godnr].path_denied&PATH_TURNING))
if((i=nstrtok(enemy,","))>0) {
char tmpbuf[MAX_BUF];
sprintf(buf,"The holy words of %s have the power to\n",name);
strcat(buf,"slay creatures belonging to the ");
if(i>1)
sprintf(tmpbuf,"following \n races:%s",
strtoktolin(enemy,","));
else
sprintf(tmpbuf,"race of%s",strtoktolin(enemy,","));
sprintf(buf,"%s%s\n ---\n",buf,tmpbuf);
}
}
if(level==4&&RANDOM()%2) { /* Priest of god gets these protect,vulnerable... */
int has_effect=0,tmpvar;
char tmpbuf[MAX_BUF];
sprintf(tmpbuf,"%s has a potent aura which is extended\n"
,name);
strcat(tmpbuf,"faithful priests. The effects of this aura include:\n");
if((tmpvar=Gods[godnr].protected)) {
has_effect = 1;
DESCRIBE_ABILITY(tmpbuf, tmpvar, "Protected");
}
if(strlen(tmpbuf)>38) sprintf(tmpbuf,"%s\n",tmpbuf);
if((tmpvar=Gods[godnr].vulnerable)) {
has_effect = 1;
DESCRIBE_ABILITY(tmpbuf, tmpvar, "Vulnerable");
}
if(has_effect) {
strcat(buf,tmpbuf);
strcat(buf,"\n ---\n");
} else
sprintf(buf," ");
}
if(level==5&&RANDOM()%2) { /* aligned race, summoning */
char *race=Gods[godnr].aligned_race;
if(race&&!(Gods[godnr].path_denied&PATH_SUMMON))
if((i=nstrtok(race,","))>0) {
char tmpbuf[MAX_BUF];
sprintf(buf,"Creatures sacred to %s include the \n",name);
if(i>1)
sprintf(tmpbuf,"following \n races:%s",
strtoktolin(race,","));
else
sprintf(tmpbuf,"race of%s",strtoktolin(race,","));
sprintf(buf,"%s%s\n ---\n",buf,tmpbuf);
}
}
if(level==6&&RANDOM()%2) { /* blessing,curse properties of the god */
int has_effect=0,tmpvar;
char tmpbuf[MAX_BUF];
sprintf(tmpbuf,"\n");
sprintf(tmpbuf,"The priests of %s are known to be able to \n"
,name);
if((tmpvar=Gods[godnr].protected)) {
has_effect = 1;
strcat(tmpbuf,"bestow a blessing which makes the recipient\n");
DESCRIBE_ABILITY(tmpbuf, tmpvar, "Protected");
}
if((tmpvar=Gods[godnr].vulnerable)) {
strcat(tmpbuf,"\n");
if(has_effect) strcat(tmpbuf,"and ");
else has_effect = 1;
strcat(tmpbuf,"lay a curse which makes the recipient\n");
DESCRIBE_ABILITY(tmpbuf, tmpvar, "Vulnerable");
}
if(has_effect) {
strcat(buf,tmpbuf);
strcat(buf,"\n ---\n");
} else
sprintf(buf," ");
}
if(level==8&&RANDOM()%2) { /* immunity, holy possession */
int has_effect=0,tmpvar;
char tmpbuf[MAX_BUF];
sprintf(tmpbuf,"\n");
sprintf(tmpbuf,"The priests of %s are known to make cast a mighty \n"
,name);
if((tmpvar=Gods[godnr].immune)) {
has_effect = 1;
strcat(tmpbuf,"prayer of possession which gives the recipient\n");
DESCRIBE_ABILITY(tmpbuf, tmpvar, "Immunity");
}
if(has_effect) {
strcat(buf,tmpbuf);
strcat(buf,"\n ---\n");
} else
sprintf(buf," ");
}
if(level==12&&RANDOM()%2) { /* spell paths */
int has_effect=0,tmpvar;
char tmpbuf[MAX_BUF];
sprintf(tmpbuf,"\n");
sprintf(tmpbuf,"It is rarely known fact that the priests of %s\n"
,name);
strcat(tmpbuf,"are mystically transformed. Effects of this include:\n"); if((tmpvar=Gods[godnr].path_attuned)) {
has_effect = 1;
DESCRIBE_PATH(tmpbuf, tmpvar, "Attuned");
}
if((tmpvar=Gods[godnr].path_repelled)) {
has_effect = 1;
DESCRIBE_PATH(tmpbuf, tmpvar, "Repelled");
}
if((tmpvar=Gods[godnr].path_denied)) {
has_effect = 1;
DESCRIBE_PATH(tmpbuf, tmpvar, "Denied");
}
if(has_effect) {
strcat(buf,tmpbuf);
strcat(buf,"\n ---\n");
} else
sprintf(buf," ");
}
/* check to be sure new buffer size dont exceed either
* the maximum buffer size, or the 'natural' size of the
* book...
*/
if(book_overflow(retbuf,buf,booksize))
break;
else if(strlen(buf)>1) strcat(retbuf,buf);
level--;
}
if(strlen(retbuf)==introlen) { /* we got no information beyond the preamble! */
strcat(retbuf," [Unfortunately the rest of the information is\n");
strcat(retbuf," hopelessly garbled!]\n ---\n");
}
#ifdef BOOK_MSG_DEBUG
LOG(llevDebug,"\n god_info_msg() created strng: %d\n",strlen(retbuf));
fprintf(logfile," MADE THIS:\n%s",retbuf);
#endif
return retbuf;
}
int book_overflow(char *buf1, char *buf2, int booksize) {
if( buf_overflow(buf1,buf2,BOOK_BUF-2) /* 2 less so always room for trailing \n */
|| buf_overflow(buf1,buf2,booksize))
return 1;
return 0;
}
/* HANDMADE STRING FUNCTIONS.., perhaps these belong in another file
* (shstr.c ?), but the quantity BOOK_BUF will need to be defined. */
/* buf_overflow() - we don't want to exceed the buffer size of
* buf1 by adding on buf2! Returns true if overflow will occur.
*/
int buf_overflow(char *buf1, char *buf2, int bufsize) {
int len1=0,len2=0;
if(buf1) len1=strlen(buf1);
if(buf2) len2=strlen(buf2);
if((len1+len2)>=bufsize) return 1;
return 0;
}
/* nstrtok() - simple routine to return the number of list
* items in buf1 as separated by the value of buf2
*/
int nstrtok (char *buf1, char *buf2) {
char *tbuf,sbuf[12],buf[MAX_BUF];
int number=0;
if(!buf1||!buf2) return 0;
sprintf(buf,"%s",buf1);
sprintf(sbuf,"%s",buf2);
tbuf=strtok(buf,sbuf);
while(tbuf) {
number++;
tbuf = strtok(NULL,sbuf);
}
return number;
}
/* strtoktolin() - takes a string in buf1 and separates it into
* a list of strings delimited by buf2. Then returns a comma
* separated string w/ decent punctuation.
*/
char *strtoktolin (char *buf1, char *buf2) {
int maxi, i = nstrtok(buf1,buf2);
char *tbuf, buf[MAX_BUF], sbuf[12];
static char rbuf[BOOK_BUF];
maxi = i;
sprintf(buf,"%s",buf1);
sprintf(sbuf,"%s",buf2);
sprintf(rbuf," ");
tbuf = strtok(buf,sbuf);
while(tbuf&&i>0) {
strcat(rbuf,tbuf);
i--;
if(i==1&&maxi>1) strcat(rbuf," and ");
else if(i>0&&maxi>1) strcat(rbuf,", ");
else strcat(rbuf,".");
tbuf = strtok(NULL,sbuf);
}
return (char *) rbuf;
}